package com.yvan.cs.utils;

import com.fasterxml.jackson.databind.JsonNode;
import com.google.common.base.Joiner;
import com.google.common.base.Splitter;
import com.google.common.collect.Lists;
import com.yvan.cs.platform.Conv;
import com.yvan.cs.platform.JsonWapper;
import com.yvan.cs.platform.YvanUtil;
import lombok.Cleanup;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import lombok.val;
import org.apache.commons.io.IOUtils;

import java.io.File;
import java.io.FileInputStream;
import java.io.InputStream;
import java.util.List;

import static com.yvan.cs.platform.YvanUtil.objectYamlMapper;

@Slf4j
public class FileUtils {

    /**
     * 规范相对路径
     * 如果list中包含 ./ 或 / 开头的路径，将会取消掉之前的路径设置
     */
    public static String normalizePath(Object... paths) {
        if (paths.length == 0) {
            return "";
        }
        List<String> fs = Lists.newArrayList();
        for (Object obj : paths) {
            if (obj instanceof String) {
                String v = ((String) obj);
                v = v.trim().replace("\\", "/");
                if (v.startsWith("/") || v.startsWith("./")) {
                    fs.clear();
                }
                fs.add(v);

            } else if (obj instanceof List) {
                for (Object o : (List) obj) {
                    String v = Conv.NS(o);
                    v = v.trim().replace("\\", "/");
                    if (v.startsWith("/") || v.startsWith("./")) {
                        fs.clear();
                    }
                    fs.add(v);
                }

            } else if (obj instanceof String[]) {
                for (String v : (String[]) obj) {
                    v = v.trim().replace("\\", "/");
                    if (v.startsWith("/") || v.startsWith("./")) {
                        fs.clear();
                    }
                    fs.add(v);
                }
            } else if (obj instanceof Object[]) {
                for (Object o : (Object[]) obj) {
                    String v = Conv.NS(o);
                    v = v.trim().replace("\\", "/");
                    if (v.startsWith("/") || v.startsWith("./")) {
                        fs.clear();
                    }
                    fs.add(v);
                }
            }
        }


        final String path = Joiner.on("/").join(fs);
        List<String> vs = Splitter.on('/').omitEmptyStrings().splitToList(path.replace("\\", "/"));
        return Joiner.on("/").join(vs);
    }


    /**
     * 获取 File 对象，如果 File 不存在 则抛出 ResourceFoundException 异常
     */
    @SneakyThrows
    public static File getResource(Object... paths) {
        return new File(normalizePath(paths));
    }

    /**
     * 获取 File 对象，并准备进入写入状态。如果不允许写入，则抛出异常
     */
    @SneakyThrows
    public static File getWriteFile(Object... paths) {
        val file = new File(normalizePath(paths));
        log.debug("write {}", file.getCanonicalPath());
        return file;
    }

    /**
     * 获取 File 对象，但并不校验文件是否存在，或是否允许读写
     */
    @SneakyThrows
    public static File getResourceQuietly(Object... paths) {
        val file = new File(normalizePath(paths));
        log.debug("qtryread {}", file.getCanonicalPath());
        return file;
    }

    /**
     * 读取 yaml 文件，并进行对象转换
     */
    @SneakyThrows
    public static <T> T readYaml(Class<T> clazz, Object... location) {
        val file = getResource(location);
        @Cleanup InputStream is = new FileInputStream(file);
        return objectYamlMapper.readValue(is, clazz);
    }

    /**
     * 写入 yaml 文件
     */
    @SneakyThrows
    public static void writeYaml(Object object, Object... location) {
        val file = getWriteFile(location);
        objectYamlMapper.writerWithDefaultPrettyPrinter().writeValue(file, object);
    }

    @SneakyThrows
    public static void write(String content, File file) {
        YvanUtil.saveToFile(file.getCanonicalPath(), content);
    }

    /**
     * 读取 yaml 文件，并返回 json操作类
     */
    @SneakyThrows
    public static JsonWapper readYaml(Object... location) {
        JsonNode jsonNode = readYamlToJsonNode(location);
        return new JsonWapper(jsonNode);
    }

    /**
     * 读取 yaml 文件，并返回 JsonNode 类
     */
    @SneakyThrows
    public static JsonNode readYamlToJsonNode(Object... location) {
        val file = getResource(location);
        @Cleanup InputStream is = new FileInputStream(file);
        return objectYamlMapper.readTree(is);
    }

    /**
     * 读取目标文件，并返回文件的所有内容，如果文件不存在，则抛出 ResourceFoundException 异常
     */
    public static String readContent(Object... location) {
        return readContent(getResource(location));
    }

    /**
     * 读取目标文件，并返回文件的所有内容
     */
    @SneakyThrows
    public static String readContent(File file) {
        if (!file.exists()) {
            return "";
        }
        @Cleanup InputStream is = new FileInputStream(file);
        List<String> lines = IOUtils.readLines(is, "UTF-8");
        return Joiner.on("\n").join(lines);
    }
}
